fix(web): render local images inline - #5114
Conversation
AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a new feature enabling inline rendering of local workspace images. It adds new user-facing behavior with a new component that fetches signed asset URLs, touches multiple layers (server projection, web rendering, clipboard handling), and warrants human review to verify the integration across these components. You can customize Macroscope's approvability policy. Learn more. |
Use the preserved activity detail when nested provider image data is removed during transport projection. Add regression coverage for the projected production payload shape. Addresses pingdotgg#5114 (comment) AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Reject non-path image detail summaries and recover projected structured image paths before rendering. Preserve original Markdown image sources when copying so signed asset URLs do not leave the app. Addresses pingdotgg#5114 (comment) Addresses pingdotgg#5114 (comment) AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Add integration coverage for the existing Windows work-log image path flow. This changes no production behavior; it confirms that Markdown URL sanitization already preserves the decoded path for signed asset requests. Documents pingdotgg#5114 (comment) as a false positive. AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Add clipboard coverage proving that percent-encoded Windows image paths resolve back to the original workspace path. This changes no production behavior and confirms the copied Markdown remains functional. Documents pingdotgg#5114 (comment) as a false positive. AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
|
Tested this PR locally and it fixed the issue for me. Environment: Ubuntu 24.04.4 LTS (Debian-based), x86_64, kernel 7.0.0-28-generic, T3 Code AppImage. I built PR head Both local Markdown images and |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3ec9e15. Configure here.
Preserve structured savedPath values in projected item data so generated images still render when the human-readable activity detail is truncated. Addresses pingdotgg#5114 (comment) AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
|
up |
Both are fallout from resolving this sync's conflicts, caught by tsc rather than by a test. ChatMarkdown had two `img` handlers after the pingdotgg#5114 merge: upstream's, which exists only to drop the native `title` attribute, and the pull request's, which resolves a workspace image path. Merged into one that does both. ChatComposer lost the `getProviderDisplayName` import when the plan usage commit's import hunk was resolved in upstream's favour, while the call site it feeds survived. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit d96437f909c1ff8e6c26a02ce80cbb8511dad51e)
All four are fallout from replaying the carried set onto 50 new upstream commits, caught by tsgo and the targeted suites rather than by the merge. The settled preview reaper passed `changeRequestState` to `effectiveSettled`, which upstream renamed to `changeRequest`. The traits picker's own test grew upstream's required `planModeEnabled` input, since the fork's `excludeDescriptorIds` parameter now sits beside it rather than in its place. Two tests describe behaviour upstream changed underneath them. pingdotgg#7152 folds a tool-only work group behind a "+N tool calls" toggle and keeps only the last entry of a group visible, so the pingdotgg#5114 image row assertion was reading a collapsed group; the entry now sits last in a mixed group, which is the shape that renders it inline. pingdotgg#7252 mutes browser tabs on attach, so the fork's hand-rolled fake webContents needs `setAudioMuted` and `isCurrentlyAudible` like upstream's shared fake already has. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Hi there, I will stop updating to upstream until get I a go. Local images still dont render as I am writing this. Not a big deal, but would be nice to have. @maintainers: feel free to close this, if it is not needed anymore, I wont have any hard feelings about this Peace, nerds! |
Both go in the Fixes table ahead of the build, so the fork overview ships current. No change to the carried pull requests: pingdotgg#4989 and pingdotgg#5114 are both still open upstream as of today, and pingdotgg#5114's head is still the pinned b9f2090. Written by Claude Opus 5 in T3 Code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…for upstream's Upstream merged pingdotgg#6433 today, its own implementation of inline workspace images in chat markdown, on both web and mobile. That collided with the carried pingdotgg#5114 renderer in the one place it could not be seen: both defined an `img` key in the same `markdownComponents` object literal, so upstream's silently won at runtime and the fork's became dead code. Only `tsgo` noticed, as a duplicate identifier. Removes the fork's `img` handler, its `MarkdownWorkspaceImage` component and a duplicated `useAssetUrlState` import. Upstream's `ChatMarkdownWorkspaceImage` is now the only path, and its own six tests cover it. The work-log half of pingdotgg#5114 is NOT superseded and stays: `session-logic` still uses `resolveMarkdownImageFileLinkMeta` to surface a generated or changed image as its own activity row, which upstream does not do.
|
Note 🤖 GPT-5.6 Sol responding on behalf of Theo Closing this PR after an automated pass over open pull requests. Workspace image rendering already shipped in #6433. |
New upstream base, the palette fleet spawn in the Interface table, pingdotgg#5114 now closed upstream without merging, and the chat anchor row updated for upstream pingdotgg#7971 landing a mid-turn release that does not cover the settle case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Problem
Local workspace images referenced in chat Markdown render as broken placeholders, even though the same paths work as file links. Image generation and
view_imagealso provide local paths that were not surfaced as visible image output.Fixes #2398.
Fix
file://workspace image sources through T3 Code's existing signed asset URLs.imageGeneration.savedPathandimageView.pathlifecycle data and render those outputs inline in the work log.This reuses the existing workspace asset boundary: paths are resolved against the thread workspace and served through expiring signed URLs instead of exposing raw local-file URLs.
Screenshots
The screenshots for generated image output and workspace images rendered through Markdown were captured with a local development build and will be attached separately.
Validation
pnpm exec vp test run apps/web/src/markdown-links.test.ts apps/web/src/session-logic.test.ts apps/server/src/provider/Layers/CodexAdapter.test.ts— 122 tests passedpnpm exec vp run --filter @t3tools/web typecheckpnpm exec vp run --filter t3 typecheckview_imageyou can see the before in the linked issue
Checklist
🤖 Implementation and tests were generated with OpenAI Codex (GPT-5.6 Sol) through the T3 Code Codex harness, then reviewed and verified in a local development build.
Note
Low Risk
UI and asset-display changes reusing the existing signed workspace-file boundary; no auth or persistence changes.
Overview
Fixes broken local image placeholders by routing workspace image paths through the existing signed asset URL flow instead of raw
file:URLs.Chat Markdown adds
resolveMarkdownImageFileLinkMetaand aMarkdownWorkspaceImagecomponent that resolves relative, absolute, andfile://image sources against the thread workspace. The sanitize schema now allowsfile:onimgsrc; remote images are unchanged.Work log derives an
imagePathonimage_viewentries from CodexsavedPath/path, Claude file lists, and image-like details, then renders inline previews under the row viaChatMarkdown. Server keepssavedPathin activity payload projection and maps CodexsavedPathinto lifecycle detail.Clipboard stores the original markdown source on
data-markdown-srcso copy/paste round-trips workspace paths (including encoded Windows paths) rather than expiring signed URLs.Reviewed by Cursor Bugbot for commit b9f2090. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Render local workspace images inline in chat work log entries
MarkdownWorkspaceImagecomponent in ChatMarkdown.tsx that resolves workspace file paths to signed asset URLs and renders them inline, with loading/error fallbacks.SimpleWorkEntryRowin MessagesTimeline.tsx to display an inline image whenworkEntry.imagePathis set and athreadRefis available.imagePathtoWorkLogEntryin session-logic.ts, derived fromitem.savedPath,item.path,changedFiles, orpayload.detailforimage_viewactivities.data-markdown-src) rather than signed URLs when copying images.ActivityPayloadProjectionto retainsavedPaththrough payload projection so image paths survive to the frontend.Macroscope summarized b9f2090.